#include "VisCamController.h"
#include "Settings.h"
#include "InputManager.h"
#include "Overseer.h"
#include <OgreCamera.h>

VisCamController::VisCamController(Ogre::Camera *cam) 
    : camera(cam), camAcceleration(Ogre::Vector3::ZERO), camVelocity(Ogre::Vector3::ZERO), 
      goingForward(false), goingBack(false), goingLeft(false), goingRight(false), goingUp(false), goingDown(false)
{
    Settings *settings = Settings::getSingletonPtr();
    topSpeed = settings->getSetting<double>("General.CameraSpeed");

    InputManager *im = Overseer::getSingletonPtr()->getInputManager();

    forwardKey = im->getKeyCode(settings->getSetting<std::string>("Input.ForwardKey"));
    backwardKey = im->getKeyCode(settings->getSetting<std::string>("Input.BackwardKey"));
    leftKey = im->getKeyCode(settings->getSetting<std::string>("Input.LeftKey"));
    rightKey = im->getKeyCode(settings->getSetting<std::string>("Input.RightKey"));
    upKey = im->getKeyCode(settings->getSetting<std::string>("Input.UpKey"));
    downKey = im->getKeyCode(settings->getSetting<std::string>("Input.DownKey"));
    fastKey = im->getKeyCode(settings->getSetting<std::string>("Input.SpeedKey"));
    
}

void VisCamController::update(double timeSinceLastFrame)
{
    camAcceleration = Ogre::Vector3::ZERO;
    if (goingForward) camAcceleration += camera->getDirection();
    if (goingBack) camAcceleration -= camera->getDirection();
    if (goingLeft) camAcceleration -= camera->getRight();
    if (goingRight) camAcceleration += camera->getRight();
    if (goingUp) camAcceleration += camera->getUp();
    if (goingDown) camAcceleration -= camera->getUp();

    if (camAcceleration.squaredLength() != 0)
    {
        camAcceleration.normalise();
        camVelocity += camAcceleration * topSpeed * timeSinceLastFrame * 10;
    }
    else camVelocity -= camVelocity * timeSinceLastFrame * 10;

    Ogre::Real epsilon = std::numeric_limits<Ogre::Real>::epsilon();

    if (camVelocity.squaredLength() > topSpeed*topSpeed)
    {
        camVelocity.normalise();
        camVelocity *= topSpeed;
    }
    else if (camVelocity.squaredLength() < epsilon * epsilon) camVelocity = Ogre::Vector3::ZERO;

    if (camVelocity != Ogre::Vector3::ZERO) camera->move(camVelocity * timeSinceLastFrame);
}

bool VisCamController::keyPressed(const OIS::KeyEvent &evt)
{
    if (evt.key == forwardKey) goingForward = true;
    else if (evt.key == backwardKey) goingBack = true;
    else if (evt.key == leftKey) goingLeft = true;
    else if (evt.key == rightKey) goingRight = true;
    else if (evt.key == upKey) goingUp = true;
    else if (evt.key == downKey) goingDown = true;
    else if (evt.key == fastKey) topSpeed *= 10.0;
    return true;
}
bool VisCamController::keyReleased(const OIS::KeyEvent &evt)
{
    if (evt.key == forwardKey) goingForward = false;
    else if (evt.key == backwardKey) goingBack = false;
    else if (evt.key == leftKey) goingLeft = false;
    else if (evt.key == rightKey) goingRight = false;
    else if (evt.key == upKey) goingUp = false;
    else if (evt.key == downKey) goingDown = false;
    else if (evt.key == fastKey) topSpeed /= 10.0;
    return true;
}
bool VisCamController::mouseMoved(const OIS::MouseEvent &evt)
{
    camera->yaw(Ogre::Degree(-evt.state.X.rel * 0.15f));
    camera->pitch(Ogre::Degree(-evt.state.Y.rel * 0.15f));
    return true;
}
bool VisCamController::mousePressed(const OIS::MouseEvent &evt, OIS::MouseButtonID id)
{
    return true;
}
bool VisCamController::mouseReleased(const OIS::MouseEvent &evt, OIS::MouseButtonID id)
{
    return true;
}
